﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Audio;

namespace DarwinIsDead.Traits {
    class AbsorbShot : Trait {
        private Bullet absorbedBullet;
        private Player player;

        /// <summary>
        /// Initial size of the absorbed bullet.
        /// </summary>
        public Vector2 BulletSize { get; private set; }

        /// <summary>
        /// Initial damage of the absorbed bullet
        /// </summary>
        public int InitialDamageCapacity { get; private set; }
        public int DamageCapacity { get; private set; }
        public float CapacityGrowthRate { get; private set; }
        private int currentDamage;

        /// <summary>
        /// </summary>
        public float DamageGrowthRate { get; private set; }
        private float damageModifier;
        /// <summary>
        /// How fast the absorbed bullet is fired
        /// </summary>
        public float MuzzleSpeed { get; private set; }

        /// <summary>
        /// How far the bullet goes before dissipating
        /// </summary>
        public float Range { get; private set; }

        private SpriteFont debugFont;

        public AbsorbShot(World world, Vector2 bulletSize, float muzzleSpeed,
            int damageCapacity, float capacityGrowthRate, float range,
            float damageGrowthRate)
            : base(null, world) {
                BulletSize = bulletSize;
                InitialDamageCapacity = DamageCapacity = damageCapacity;
                CapacityGrowthRate = capacityGrowthRate;
                DamageGrowthRate = damageModifier = damageGrowthRate;
                MuzzleSpeed = muzzleSpeed;
                Range = range;

                currentDamage = 0;
        }

        public override void Initialize() {
            //absorbedBullet = new Bullets.Linear(World, BulletSize,
            //    false, 0, MuzzleSpeed, Range);
            absorbedBullet = new Bullets.Linear(World, 0, MuzzleSpeed, Range,
                false);

            absorbedBullet.NotifyDamage += Owner.AddDamage;
            absorbedBullet.NotifyDamage += ResetBullet;

            List<Entity> players = World.GetEntities<Player>();
            if (players.Count > 0) {
                player = (Player)players[0];
            }

            World.AddEntity(absorbedBullet);

            debugFont = World.Game.Content.Load<SpriteFont>("Fonts\\Courier New");
        }

        public override object Clone() {
            AbsorbShot ret = new AbsorbShot(World, BulletSize,
                MuzzleSpeed, DamageCapacity, CapacityGrowthRate, Range,
                DamageGrowthRate);
            return ret;
        }

        public override void Dispose() {
            World.RemoveEntity(absorbedBullet);
        }

        protected override void AdjustLevel(int level) {
            damageModifier = level * DamageGrowthRate;
            DamageCapacity = (int)(InitialDamageCapacity * level *
                CapacityGrowthRate);
        }

        public override void Collision(Entity other, Rectangle overlap) {
            if (other is Bullet) {
                if (!absorbedBullet.Active) {
                    Bullet bullet = (Bullet)other;
                    if (bullet.Friendly) {
                        // Add the strength of the absorbed bullet to our
                        // own, modified by level
                        currentDamage += (int)(bullet.Damage *
                            damageModifier + 0.5f);
                    }
                }
            }
        }

        protected override void InternalUpdate(GameTime gameTime) {
            // Delta time
            float dt = (float)gameTime.ElapsedGameTime.Milliseconds / 1000f;

            if (!absorbedBullet.Active && currentDamage > DamageCapacity) {
                // Fire the bullet if it's beyond a certain strength
                float dx = player.Position.X - Owner.Position.X;
                float dy = player.Position.Y - Owner.Position.Y;

                float dir = (float)Math.Atan2(dy, dx);

                absorbedBullet.Damage = currentDamage;
                absorbedBullet.Fire(Owner.Position, dir);
                currentDamage = 0;
            }
        }

        protected override void InternalDraw(SpriteBatch spriteBatch, Color color) {
            spriteBatch.DrawString(
                debugFont, "Absorbed Damage: " + currentDamage,
                new Vector2(Owner.Position.X, Owner.Position.Y + 20f),
                color
            );
                
        }

        public void ResetBullet(int damage) {
            absorbedBullet.Damage = 0;
        }
    }
}
